{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Teleportation experiment from paper by Fedortchenko\n",
    "\n",
    "This notebook uses Qubiter to illustrate a pedagogical Teleportation \n",
    "experiment performed by S. Fedortchencko on IBM Quantum Experience, \n",
    "and described by him in the paper\n",
    "\n",
    ">https://arxiv.org/abs/1607.02398\n",
    "\n",
    "$$\\newcommand{\\bra}[1]{\\left\\langle{#1}\\right|}$$\n",
    "$$\\newcommand{\\ket}[1]{\\left|{#1}\\right\\rangle}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First change your working directory to the qubiter directory in your computer, and add its path to the path environment variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks\n",
      "/home/rrtucci/PycharmProjects/qubiter\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "print(os.getcwd())\n",
    "os.chdir('../../')\n",
    "print(os.getcwd())\n",
    "sys.path.insert(0,os.getcwd())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loaded OneQubitGate, WITHOUT autograd.numpy\n"
     ]
    }
   ],
   "source": [
    "from qubiter.SEO_writer import *\n",
    "from qubiter.SEO_simulator import *\n",
    "from qubiter.StateVec import *\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Number of qubits is 3.\n",
    "Note that we use \"bit\" for both qbits and cbits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_qbits = 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Use a trivial circuit embedder that embeds 3 qubits into same 3 qubits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "emb = CktEmbedder(num_qbits, num_qbits)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Open a writer, tell it where to write to.\n",
    "We will use zero bit last (ZL) convention"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_prefix = 'teleportation-fedor'\n",
    "wr = SEO_writer(file_prefix, emb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Write partial circuit that creates\n",
    "a state at qbit 0 that will be teleported to qbit 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "[[[0.65328148-0.65328148j 0.        +0.j        ]\n",
      "  [0.        +0.j         0.        +0.j        ]]\n",
      "\n",
      " [[0.27059805-0.27059805j 0.        +0.j        ]\n",
      "  [0.        +0.j         0.        +0.j        ]]]\n",
      "total probability of state vector (=one if no measurements)= 1.000000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (0.853553, 0.146447), 1: (1.0, 0.0), 2: (1.0, 0.0)}\n"
     ]
    }
   ],
   "source": [
    "z_axis = 3\n",
    "def init_ckt():\n",
    "    wr.write_one_qbit_gate(0, OneQubitGate.had2)  # H(0)\n",
    "    wr.write_one_qbit_gate(0, OneQubitGate.rot_ax, [-np.pi/8, z_axis])  # T(0)\n",
    "    wr.write_one_qbit_gate(0, OneQubitGate.had2)  # H(0)\n",
    "    wr.write_one_qbit_gate(0, OneQubitGate.rot_ax, [-np.pi/4, z_axis])  # S(0)\n",
    "init_ckt()\n",
    "wr.close_files()\n",
    "\n",
    "init_st_vec = StateVec.get_standard_basis_st_vec([0, 0, 0])\n",
    "sim = SEO_simulator(file_prefix, num_qbits, init_st_vec)\n",
    "StateVec.describe_st_vec_dict(sim.cur_st_vec_dict, print_st_vec=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now run the whole circuit.\n",
    "If you want to see the state vector after only first n gates,\n",
    "where n is less than total number of gates, just\n",
    "comment out all gates from n+1 to the final one. You can comment\n",
    "multiple lines with control-slash applied to a selected block. \n",
    "control-slash also uncomments a selected, commented block."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*********branch= pure\n",
      "state vector:\n",
      "[[[0.32664074-0.32664074j 0.13529903-0.13529903j]\n",
      "  [0.        +0.j         0.        +0.j        ]]\n",
      "\n",
      " [[0.        +0.j         0.        +0.j        ]\n",
      "  [0.        +0.j         0.        +0.j        ]]]\n",
      "total probability of state vector (=one if no measurements)= 0.250000\n",
      "dictionary with key=qubit, value=(Prob(0), Prob(1))\n",
      "{0: (1.0, 0.0), 1: (1.0, 0.0), 2: (0.853553, 0.146447)}\n"
     ]
    }
   ],
   "source": [
    "wr = SEO_writer(file_prefix, emb)\n",
    "init_ckt()\n",
    "wr.write_one_qbit_gate(2, OneQubitGate.had2)  # H(2)\n",
    "\n",
    "control_pos = 2\n",
    "target_pos = 1\n",
    "trols = Controls.new_single_trol(num_qbits, control_pos, kind=True)\n",
    "wr.write_controlled_one_qbit_gate(target_pos, trols, OneQubitGate.sigx)\n",
    "\n",
    "control_pos = 0\n",
    "target_pos = 1\n",
    "trols = Controls.new_single_trol(num_qbits, control_pos, kind=True)\n",
    "wr.write_controlled_one_qbit_gate(target_pos, trols, OneQubitGate.sigx)\n",
    "\n",
    "wr.write_one_qbit_gate(0, OneQubitGate.had2)  # H(0)\n",
    "\n",
    "wr.write_MEAS(tar_bit_pos=0, kind=0)\n",
    "wr.write_MEAS(tar_bit_pos=1, kind=0)\n",
    "wr.close_files()\n",
    "\n",
    "init_st_vec = StateVec.get_standard_basis_st_vec([0, 0, 0])\n",
    "sim = SEO_simulator(file_prefix, num_qbits, init_st_vec)\n",
    "StateVec.describe_st_vec_dict(sim.cur_st_vec_dict, print_st_vec=True)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Look in files\n",
    "* <a href=\"../io_folder/teleportation-fedor_3_eng.txt\">../io_folder/teleportation-fedor_3_eng.txt</a>\n",
    "* <a href=\"../io_folder/teleportation-fedor_3_ZLpic.txt\">../io_folder/teleportation-fedor_3_ZLpic.txt</a>\n",
    "\n",
    "to see the quantum circuit that was generated"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "If you do the algebra, the final state vector should be\n",
    "\n",
    "$\n",
    "\\begin{array}{c}\\ket{0}\\\\ \\ket{0} \\\\ (\\frac{cc}{2} \\ket{0} + \\frac{ss}{2}\\ket{1}\\end{array}+\n",
    "\\begin{array}{c}\\ket{0} \\\\ \\ket{1} \\\\ (\\frac{cc}{2} \\ket{0} + \\frac{ss}{2}\\ket{1})\\end{array}+\n",
    "\\begin{array}{c}\\ket{1} \\\\ \\ket{0} \\\\ (\\frac{cc}{2} \\ket{0} - \\frac{ss}{2}\\ket{1})\\end{array}+\n",
    "\\begin{array}{c}\\ket{1} \\\\ \\ket{1} \\\\ (\\frac{-ss}{2} \\ket{0} + \\frac{cc}{2}\\ket{1})\\end{array}\n",
    "$\n",
    "\n",
    "where cc = cos(\\pi/8) and ss = sin(\\pi/8), and where the \n",
    "first, second,\n",
    "third\n",
    "row corresponds to qubit 0, 1, 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "toc": {
   "colors": {
    "hover_highlight": "#DAA520",
    "running_highlight": "#FF0000",
    "selected_highlight": "#FFD700"
   },
   "moveMenuLeft": true,
   "nav_menu": {
    "height": "51px",
    "width": "252px"
   },
   "navigate_menu": true,
   "number_sections": true,
   "sideBar": true,
   "threshold": 4,
   "toc_cell": false,
   "toc_section_display": "block",
   "toc_window_display": false,
   "widenNotebook": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
